using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace Jonathan.Tabber
{
    public partial class TabberGroup : UserControl
    {
        #region Variables

        private Point m_DownPoint;
        private Tabber m_Tabber;
        private int m_ReorderIndex;
        private bool m_GridShown;
        private FlowLayoutPanel m_GridPanel;
        private frmFloatingGroup m_Floating;

        #endregion

        #region Constructor

        /// <summary>
        /// Creates a new TabberGroup...
        /// </summary>
        /// <param name="tabber">Parent Tabber Control</param>
        public TabberGroup(Tabber tabber)
        {
            InitializeComponent();

            this.m_Tabber = tabber;
            this.btnTabMenu.MouseUp += new MouseEventHandler(btnTabMenu_MouseUp);
            this.Dock = DockStyle.Fill;
            this.m_DownPoint = new Point(0, 0);
            this.m_ReorderIndex = -1;
            this.m_GridShown = false;
            this.m_Floating = null;
            
            this.TabPanel.MouseDoubleClick += new MouseEventHandler(TabPanel_MouseDoubleClick);

            this.m_GridPanel = new FlowLayoutPanel();
            this.m_GridPanel.BackColor = Color.White;
            this.m_GridPanel.AutoScroll = true;
            this.m_GridPanel.Anchor = AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Left | AnchorStyles.Bottom;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets the Selected TabberPage...
        /// </summary>
        public TabberPage SelectedTab
        {
            get
            {
                for (int a = 0; a < this.TabPanel.Controls.Count; a++)
                {
                    if (((TabButton)this.TabPanel.Controls[a]).Page.Selected)
                    {
                        return ((TabButton)this.TabPanel.Controls[a]).Page;
                    }
                }
                return null;
            }
        }

        /// <summary>
        /// Gets an array list of the Tabs in the Group...
        /// </summary>
        public TabberPage[] Tabs
        {
            get
            {
                TabberPage[] pages = new TabberPage[this.TabPanel.Controls.Count];
                for (int a = 0; a < this.TabPanel.Controls.Count; a++)
                {
                    pages[a] = ((TabButton)this.TabPanel.Controls[a]).Page;
                }
                return pages;
            }
        }

        /// <summary>
        /// Gets the Controls on the TabPanel of the group...
        /// </summary>
        internal ControlCollection TabButtons
        {
            get { return this.TabPanel.Controls; }
        }

        /// <summary>
        /// Gets the height of the tabs...
        /// </summary>
        public int TabHeight
        {
            get { return this.TabPanel.Height; }
        }

        /// <summary>
        /// Gets the Tabber Control the TabberGroup belongs to...
        /// </summary>
        public Tabber Tabber
        {
            get { return this.m_Tabber; }
        }
        #endregion

        #region Public Methods

        #region Reorder Tab

        /// <summary>
        /// Reorder the give tab to the new index...
        /// </summary>
        /// <param name="ctrl">TabButton</param>
        /// <param name="index">New Index</param>
        public void ReorderTab(Control ctrl, int index)
        {
            this.TabPanel.Controls.SetChildIndex(ctrl, index);
        }
        
        #endregion

        #region Remove Tab

        /// <summary>
        /// Removes a TabberPage from the TabberGroup...
        /// </summary>
        /// <param name="page">Page to be Removed</param>
        public void RemoveTab(TabberPage page)
        {
            // Check to see if the needs to be hid...
            if (this.m_GridShown)
            {
                this.Controls.Remove(this.m_GridPanel);
                this.m_GridShown = false;
            }

            // Change to the previous tab...
            if (page.PreviousTab != null)
            {
                this.ChangeTab(page.PreviousTab);
            }
            else if (this.Controls.Count > 1)
            {
                if (((TabberPage)this.Controls[1]) == page)
                {
                    this.Controls.RemoveAt(1);
                }
            }

            // Find and remove the button...
            for (int a = 0; a < this.TabPanel.Controls.Count; a++)
            {
                TabButton btn = (TabButton)this.TabPanel.Controls[a];
                if (btn == page.TabButton)
                {
                    // Remove links to TabberPage...
                    for (int b = 0; b < this.TabPanel.Controls.Count; b++)
                    {
                        if (((TabButton)this.TabPanel.Controls[b]).Page.PreviousTab == btn)
                        {
                            ((TabButton)this.TabPanel.Controls[b]).Page.PreviousTab = null;
                        }
                    }

                    // Remove events...
                    btn.MouseDown -= new MouseEventHandler(TabButton_MouseDown);
                    btn.MouseMove -= new MouseEventHandler(TabButton_MouseMove);
                    btn.MouseUp -= new MouseEventHandler(TabButton_MouseUp);
                    page.PreviousTab = null;

                    // Remove the Tab...
                    this.TabPanel.Controls.Remove(btn);
                }
            }

            // Remove this group if there are no more tabs left...
            if (this.TabButtons.Count == 0)
            {
                this.m_Tabber.RemoveGroup(this);
            }
            else if (this.SelectedTab == null)
            {
                this.ChangeTab((TabButton)this.TabPanel.Controls[0]);
            }

            //page.Dispose();
        }

        #endregion

        #region Add Tab

        /// <summary>
        /// Adds a TabberPage to this group...
        /// </summary>
        /// <param name="tab">TabberPage to add</param>
        public void AddTab(TabberPage tab)
        {
            // Add the Tab to the list..
            tab.SetGroup(this);

            // Correct the Height...
            tab.TabButton.Height = TabPanel.Height;

            // Add the Button to the Tab Button Panel...
            tab.TabButton.Margin = new Padding(1, 5, 0, 0);
            this.TabPanel.Controls.Add(tab.TabButton);
            this.ChangeTab(tab.TabButton);

            // Add events...
            tab.TabButton.MouseDown += new MouseEventHandler(TabButton_MouseDown);
            tab.TabButton.MouseMove += new MouseEventHandler(TabButton_MouseMove);
            tab.TabButton.MouseUp += new MouseEventHandler(TabButton_MouseUp);
        }

        #endregion

        #region Contains Tab

        /// <summary>
        /// Check to see if the Group Contains a tab with the given title...
        /// </summary>
        /// <param name="tabTitle">Title to Look for.</param>
        /// <returns>True if tab is in group; otherwise false.</returns>
        public bool ContainsTab (string tabTitle)
        {
            foreach (TabButton tb in this.TabPanel.Controls)
            {
                if (tabTitle.ToLower().Equals(tb.ButtonText.ToLower()))
                {
                    return true;
                }
            }

            return false;
        }

        #endregion

        #region Close Group

        /// <summary>
        /// Removes this Tabber Group from the Tabber...
        /// </summary>
        public void CloseGroup ()
        {
            this.m_Tabber.RemoveGroup(this);
        }

        #endregion

        #endregion

        #region Private Methods

        private void btnTabMenu_MouseUp(object sender, MouseEventArgs e)
        {
            ContextMenuStrip ctx = new ContextMenuStrip();
            ToolStripMenuItem mnu = new ToolStripMenuItem("View Tab Grid");
            mnu.Click += new EventHandler(mnu_Click);
            ctx.Items.Add(mnu);
            ctx.Items.Add(new ToolStripSeparator());
            for (int a = 0; a < this.TabPanel.Controls.Count; a++)
            {
                TabButton btn = (TabButton)this.TabPanel.Controls[a];
                ToolStripMenuItem mnuI = new ToolStripMenuItem(btn.ButtonText);
                if (btn.Page.Selected)
                {
                    mnuI.Checked = true;
                }

                if (btn.Image != null)
                {
                    mnuI.Image = btn.Image;
                }

                mnuI.Tag = btn;
                mnuI.Click += new EventHandler(mnuI_Click);
                ctx.Items.Add(mnuI);
            }
            ctx.Show(this.btnTabMenu, e.X, e.Y);
        }

        private void mnu_Click(object sender, EventArgs e)
        {
            this.m_GridPanel.Controls.Clear();

            for (int a = 0; a < this.TabPanel.Controls.Count; a++)
            {
                Bitmap bmp = new Bitmap(this.Tabs[a].Width, this.Tabs[a].Height);
                this.Tabs[a].DrawToBitmap(bmp, new Rectangle(0, 0, this.Tabs[a].Width, this.Tabs[a].Height));

                Bitmap bmp2 = new Bitmap(bmp, new Size(200, 200));

                VistaButton btn = new VistaButton();
                btn.Image = bmp2;
                btn.ImageAlign = ContentAlignment.BottomCenter;
                btn.ImageSize = new Size(200, 200);
                btn.Size = new Size(233, 233);
                btn.BaseColor = Color.Transparent;
                btn.ButtonColor = Color.Silver;
                btn.HighlightColor = Color.White;
                //btn.GlowColor = Color.Beige;
                btn.Tag = this.TabPanel.Controls[a];
                btn.ButtonText = ((TabButton)this.TabPanel.Controls[a]).ButtonText;
                btn.TextAlign = ContentAlignment.TopCenter;
                btn.ForeColor = Color.Black;
                btn.Font = new Font(btn.Font, FontStyle.Bold);

                btn.Click += new EventHandler(btn_Click);

                this.m_GridPanel.Controls.Add(btn);
            }

            this.m_GridPanel.Location = new Point(0, this.TabHeight);
            this.m_GridPanel.Size = new Size(this.Width - 2, this.Height - this.TabHeight - 2);
            this.Controls.Add(this.m_GridPanel);
            this.m_GridPanel.BringToFront();
            this.m_GridShown = true;
        }

        private void btn_Click(object sender, EventArgs e)
        {
            VistaButton btn = sender as VistaButton;
            this.ChangeTab((TabButton)btn.Tag);
        }

        private void mnuI_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem mnuI = sender as ToolStripMenuItem;
            this.ChangeTab((TabButton)mnuI.Tag);
        }

        internal void ChangeTab(TabButton btn)
        {
            if (this.m_GridShown)
            {
                this.Controls.Remove(this.m_GridPanel);
                this.m_GridShown = false;
            }
            if (this.Controls.Count > 1)
            {
                TabberPage tp = (TabberPage)this.Controls[1];
                if (tp == btn.Page)
                {
                    // Do nothing, same page...
                    return;
                }
            }

            btn.Margin = new Padding(1, 3, 0, 0);
            this.Controls.Add(btn.Page);

            if (this.Controls.Count > 2)
            {
                TabberPage tp = (TabberPage)this.Controls[1];
                tp.Selected = false;
                this.Controls.RemoveAt(1);
                tp.TabButton.Margin = new Padding(1, 5, 0, 0);
                btn.Page.PreviousTab = tp.TabButton;

                if (this.m_ReorderIndex != -1)
                {
                    this.TabPanel.Controls.SetChildIndex(tp.TabButton, this.m_ReorderIndex);
                    this.m_ReorderIndex = -1;
                }
            }
            btn.Page.Selected = true;
            btn.Page.Bounds = new Rectangle(0, this.TabPanel.Height + 2, this.Width - 2, this.Height - this.TabPanel.Height - 4);
            /*btn.ButtonColor = Color.Gray;
            btn.ForeColor = Color.Black;*/
            if (this.m_Floating != null)
            {
                this.m_Floating.Text = btn.ButtonText;
            }

            if (btn.Right > this.TabPanel.Width)
            {
                this.m_ReorderIndex = this.TabPanel.Controls.GetChildIndex(btn);
                this.TabPanel.Controls.SetChildIndex(btn, 0);
            }

            this.m_Tabber.SetPageChange(new PageEventArgs(btn.Page));
        }

        private void TabButton_MouseDown(object sender, MouseEventArgs e)
        {
            TabButton btn = sender as TabButton;
            if (e.Button == MouseButtons.Middle)
            {
                if (btn.Page.ShowCloseButton && this.m_Tabber.CloseTabsOnMiddleMouseClick)
                {
                    if (!btn.Page.Selected)
                    {
                        btn.Page.PreviousTab = this.SelectedTab.TabButton;
                    }
                    PageEventArgs pe = new PageEventArgs(btn.Page);
                    this.m_Tabber.SetRemoveEvent(pe);
                    if (!pe.Cancel)
                    {
                        this.RemoveTab(btn.Page);
                        btn.Page.Dispose();
                    }
                    return;
                }
            }
            else
            {
                this.m_DownPoint.X = e.X;
                this.m_DownPoint.Y = e.Y;

                if (btn.Page.ShowCloseButton && new Rectangle(btn.Width - 21, (btn.Height / 2) - 8, 16, 16).Contains(new Point(e.X, e.Y)))
                {
                    PageEventArgs pe = new PageEventArgs(btn.Page);
                    this.m_Tabber.SetRemoveEvent(pe);
                    if (!pe.Cancel)
                    {
                        this.RemoveTab(btn.Page);
                        btn.Page.Dispose();
                    }
                    return;
                }

                if (this.m_GridShown)
                {
                    this.Controls.Remove(this.m_GridPanel);
                    this.m_GridShown = false;
                }

                if (!btn.Page.Selected)
                {
                    this.ChangeTab(btn);
                }
            }
        }

        private void TabButton_MouseMove(object sender, MouseEventArgs e)
        {
            if (!this.m_Tabber.Dragging)
            {
                if (e.Button == MouseButtons.Left)
                {
                    if (Math.Abs(e.X - this.m_DownPoint.X) > 7 || Math.Abs(e.Y - this.m_DownPoint.Y) > 7)
                    {
                        this.m_Tabber.StartDrag(sender as TabButton);
                    }
                }
            }
            else
            {
                TabButton btn = sender as TabButton;
                this.m_Tabber.DragMove(btn.PointToScreen(new Point(e.X, e.Y)), e.X, e.Y);
            }
        }

        private void TabButton_MouseUp(object sender, MouseEventArgs e)
        {
            if (this.m_Tabber.Dragging)
            {
                this.m_Tabber.EndDrag();
            }
        }

        private void TabPanel_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.m_Tabber.CallTabPanelDoubleClick(this, e);
        }

        #endregion

        internal frmFloatingGroup Floating
        {
            get { return this.m_Floating; }

            set { this.m_Floating = value; }
        }
    }
}
